# -*- coding: utf-8 -*-
'''
Created on 2013/5/17

@author: jchchen
'''
from captcha.client import submit, displayhtml
from dajaxice.decorators import dajaxice_register
from dajaxice.utils import deserialize_form
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.db.models.signals import pre_save
from django.utils import simplejson, timezone
from django.utils.datetime_safe import datetime
from django.utils.translation import ugettext as _
from users.models import UserProfile, BDAY_LIMIT
from users.views import sendActivationMail
import logging
import settings

@dajaxice_register(method='POST', name='users.authjson')
def authjson(request, form):
    postdata = deserialize_form(form)
    action = postdata['action']
    
    em = postdata['username']
    pw = postdata['password']
    un = em
    
    if action == 'login' :
        user = authenticate(username=un, password=pw)
        if user is not None:
            login(request, user)
            return simplejson.dumps({'result': 'success_login', 'redirect_to':'/events/' })
        else:
            return simplejson.dumps({'result': 'invalid_authencate' })
 
    elif action == 'signup':
        captcha_result = check_captcha(request, postdata)
        if not captcha_result.is_valid:
            return simplejson.dumps({'result': 'captcha_fail' })
        # TODO: check at client side
        if user_is_exist(username=un, email=em) :
            # for html template display purpose
            return simplejson.dumps({'result': 'invalid_authencate' })
        else:
            pre_save.connect(default_user_active, User)
            user = User.objects.create_user(username=un, email=em, password=pw)
            try:
                sendActivationMail(request, em, un)
            except Exception as inst:
                logging.error('Exception when executing sendMail: ' + str(inst))
            us = authenticate(username=un, password=pw)
            login(request, us)
            return simplejson.dumps({'result': 'success_signup', 'redirect_to':'/events/' })
        
def check_captcha(request, post_data):
    remote_ip = request.META['REMOTE_ADDR']
    challenge = post_data.get('recaptcha_challenge_field', None)
    response = post_data.get('recaptcha_response_field', None)
    private_key = settings.RECAPTCHA_PRIVATE_KEY
    return submit(challenge, response, private_key, remote_ip)

def user_is_exist(username, email):
    """check if user is exist or not"""
    if User.objects.filter(username=username, email=email).count():
        return True
    return False

def default_user_active(sender, **kwargs):
    kwargs['instance'].is_active = True
    pre_save.disconnect(receiver=default_user_active, sender=sender)
    return

def authGetCaptcha(request):
    public_key = settings.RECAPTCHA_PUBLIC_KEY
    recaptcha_script = displayhtml(public_key=public_key, attrs={'theme' : 'clean'})
    return simplejson.dumps({'recaptcha_script': recaptcha_script })

@dajaxice_register(method='POST', name='users.profilejson')
def profilejson(request, form):
    user = request.user
    logging.info('user modify profile, user:{u}'.format(u=user))
    
    if user.is_anonymous() == True:
        logging.error('user is anonymous')
        return simplejson.dumps({'result':'illegal_user', 'msg':_('Modify failed')})
    
    opts = UserProfile._meta
    
    postdata = deserialize_form(form)
    pl = postdata.lists()
    for i, val in pl:
        if i == 'csrfmiddlewaretoken':
            continue
        
        # check only one element in a key
        if len(val) > 1 :
            logging.error('field has more than multiple values : field: {fk}, vals: {vl}'.format(fk=i, vl=val))
            return simplejson.dumps({'result':'illegal_fields_vl', 'msg':_('Modify failed')})
        
        # check model has field
        try:
            f = opts.get_field(i)
        except (FieldDoesNotExist):
            logging.error('illegal field name : field: {fk}'.format(fk=i))
            return simplejson.dumps({'result':'illegal_fields_name', 'msg':_('Modify failed')})
        
        # check content length
        if isinstance(f, models.CharField) and len(val[0]) > f.max_length:
            logging.warning('field\'s value is out of range: field: {fk}, val: {vl} l: {vll}, maxLength: {ml}'.format(fk=i, vl=val[0], vll=len(val[0]), ml=f.max_length))
            return simplejson.dumps({'result':'illegal_fields_length', 'msg':_('Modify failed')})
        
        elif isinstance(f, models.DateField) and i == 'bday':
            bdayDT = datetime.strptime(val[0], '%Y-%m-%d').date()
            td = timezone.now()
            yearsOld = td.year - bdayDT.year
            if yearsOld > BDAY_LIMIT or yearsOld <= 0:
                logging.warning('invalid bday: bday: {bd}, age: {ag}'.format(bd=str(bdayDT), ag=yearsOld))
                return simplejson.dumps({'result':'illegal_fields_bday', 'msg':_('Modify failed')})
    
    try:
        pf = user.userprofile
    except (UserProfile.DoesNotExist):
        pf = UserProfile.objects.create(user=user)
    
    try:
        pf.name = postdata.get('name', '')
        pf.gender = postdata.get('gender', '')
        pf.nationality = postdata.get('nationality', '')
        bday = postdata.get('bday', None)
        if bday is not None or len(bday) > 0: pf.bday = bday
        pf.pid = postdata.get('pid', '')
        pf.phoneNum = postdata.get('phoneNum', '')
        pf.emgcyContact = postdata.get('emgcyContact', '')
        pf.emgcyContPhone = postdata.get('emgcyContPhone', '')
        pf.modified = 1
        pf.save()
    except Exception as inst:
        logging.error('Exception when modify user profile: ' + str(inst)) 
        return simplejson.dumps({'result':'failed_modify', 'msg':_('Oops, some errors happened, we\'re working on it!')})
    
    logging.info('succeed')
    return simplejson.dumps({'result': 'success_modify', 'msg':_('Modify succeed')})
